package com.javamsg.util;

import java.io.File;
import java.io.UnsupportedEncodingException;

import org.apache.log4j.Logger;

import com.javamsg.beans.SystemData;

public class MyTools {
	private static final SystemData data = SystemData.instance();
	private static final Logger logger = Logger.getRootLogger(); 
	/**
	 * encoding String s with charset in data
	 * @param s String will be encoding
	 * @return
	 */
	public static byte[] getBytes(String s, String charsetName){
		byte[] result;
		
		try{
			result = s.getBytes(charsetName);
		}catch(UnsupportedEncodingException e){
			result = s.getBytes(); 
		}
		// TODO check this function!
		// result = s.getBytes();
		return result;
	}
	/**
	 * translate byte[] into String using this charset
	 * @param buff
	 * @param offset
	 * @param length
	 * @param charsetName
	 * @return
	 */
	public static String getString(byte[] buff, int offset, int length, String charsetName){
		String result;
		try{
			result = new String(buff, offset, length, charsetName);
		}catch(UnsupportedEncodingException e){
			result = new String(buff, offset, length);
		}
		return result;
	}
	
	public static String getString(byte[] buff, String charsetName){
		return getString(buff, 0, buff.length, charsetName);
	}
	
	/**
	 * calculate directory length recursively, if file is regular file ,just return file length
	 * @param file
	 * @return file length
	 */
	public static long calculateFileLength(File file){
		long size = 0;
		if(file.isFile()){
			size = file.length();
		}else if(file.isDirectory()){
			for(File childFile : file.listFiles()){
				size = size + calculateFileLength(childFile);
			}
		}
		return size;
	}
	/**
	 * parse this message, all result[i] must be filled!!
	 * @param message
	 * @param length
	 * @return
	 */
	public static String[] parseMessage(byte[] message, int length){
		String[] result = {"version", "packetNumber", "sender", "host", "command", "extraInfo"};
		byte colon = 58;	// ':'
		byte zero = 0;		// '0'
		int offset = 0;
		int i = 0;
		// version
		for(i = offset; i < length; i++){
			if(message[i] == colon){
				result[0] = newString(message, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		if(i >= length){
			return null;
		}
		// packet number
		for(i = offset; i < length; i++){
			if(message[i] == colon){
				result[1] = newString(message, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		if(i >= length){
			return null;
		}
		// sender
		for(i = offset; i < length; i++){
			if(message[i] == colon ){
				if(message[i + 1] == colon){
					// there is "::", skip it
					i = i + 2;
					continue;
				}else{
					result[2] = newString(message, offset, i - offset);
					result[2] = result[2].replaceAll("::", ":");
					offset = i + 1;
					break;
				}
			}
		}
		if(i >= length){
			return null;
		}
		// host
		for(i = offset; i < length; i++){
			if(message[i] == colon ){
				if(message[i + 1] == colon){
					// there is "::", skip it
					i = i + 2;
					continue;
				}else{
					result[3] = newString(message, offset, i - offset);
					result[3] = result[3].replaceAll("::", ":");
					offset = i + 1;
					break;
				}
			}
		}
		if(i >= length){
			return null;
		}
		// command
		for(i = offset; i < length; i++){
			if(message[i] == colon){
				result[4] = newString(message, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		if(i >= length){
			return null;
		}
		// extra info
		for(i = offset; i < length; i++){
			if(message[i] == zero){
				if(i == offset){
					// no extra info
					result[5] = "";
					break;
				}else{
					result[5] = newString(message, offset, i - offset);
					break;
				}
			}
		}
		if(offset == length){
			// reach message end, no extra info
			result[5] = "";
		}else if(i == length){
			result[5] = newString(message, offset, i - offset);
		}
		
		return result;
	}
	/**
	 * parse file info, all result[i] must be filled
	 * @param fileInfo
	 * @param end
	 * @return
	 */
	public static String[] parseFileInfo(byte[] fileInfo, int begin, int end){
		String[] result = {"fileNumber", "fileName", "fileSize", "fileLMT", "fileAttr"};
		byte colon = 58;	// ':'
		int i = begin;
		int offset = begin ;
		// file number
		for(i = offset; i < end; i++){
			if(fileInfo[i] == colon){
				result[0] = newString(fileInfo, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		if(i >= end){
			return null;
		}
		logger.debug("\t file number is " + result[0]);
		// file name
		for(i = offset; i < end; i++){
			if(fileInfo[i] == colon){
				if(fileInfo[i+1] == colon){
					i = i + 2;
					continue;
				}else{
					result[1] = newString(fileInfo, offset, i - offset);
					result[1] = result[1].replaceAll("::", ":");
					offset = i + 1;
					break;
				}
			}
		}
		logger.debug("\t file name is " + result[1]);
		if(i >= end){
			return null;
		}
		// file size
		for(i = offset; i < end; i++){
			if(fileInfo[i] == colon){
				result[2] = newString(fileInfo, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		logger.debug("\t file size is " + result[2]);
		if(i >= end){
			return null;
		}
		// file last modify time
		for(i = offset; i < end; i++){
			if(fileInfo[i] == colon){
				result[3] = newString(fileInfo, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		logger.debug("\t file last modify time is " + result[3]);
		if(i >= end){
			return null;
		}
		// file attribute
		result[4] = newString(fileInfo, offset, end - offset + 1);
		logger.debug("\t file attr is " + result[4]);
		return result;
		
	}
	
	public static String[] parseDirectoryInfo(byte[] header, int headerSize){
		String[] result = {"headerSize", "fileName", "fileSize", "fileAttr", "otherattr"};
		byte colon = 58;	// ':'
		int i = 0;
		int offset = 0 ;
		// header-size
		for(i = offset ; i < headerSize; i++){
			if(header[i] == colon){
				result[0] = newString(header, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		if(i >= headerSize){
			return null;
		}
		// file name
		for(i = offset; i < headerSize; i++){
			if(header[i] == colon){
				if(header[i + 1] == colon){
					i = i + 2;
					continue;
				}else{
					result[1] = newString(header, offset, i - offset);
					result[1] = result[1].replaceAll("::", ":");
					offset = i + 1;
					break;
				}
			}
		}
		if(i >= headerSize){
			return null;
		}
		// file size
		for(i = offset ; i < headerSize; i++){
			if(header[i] == colon){
				result[2] = newString(header, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		if(i >= headerSize){
			return null;
		}
		// file attribute
		for(i = offset ; i < headerSize; i++){
			if(header[i] == colon){
				result[3] = newString(header, offset, i - offset);
				offset = i + 1;
				break;
			}
		}
		if(i < headerSize){
			// other file attribute
			result[4] = newString(header, offset, headerSize - offset);
		}else{
			result[3] = newString(header, offset, headerSize - offset);
		}
		
		return result;
	}
	
	public static String newString(byte[] buff,int offset, int length){
		return MyTools.getString(buff, offset, length, data.getEncoding());
	}

}
